<template>
  <div class="container">
    <Card shadow>
      <div class="tool-container">
        <Tooltip placement="bottom-start">
          <Upload action="./" accept="application/pdf" :format="['pdf']" :show-upload-list="showUploadList" :before-upload="handleUpload">
            <Button class="import-syllabus-btn" :size="btnSize">
              导入教学大纲
              <font-awesome-icon icon="file-pdf"/>
            </Button>
          </Upload>
          <div slot="content">
            <p>导入本课程的教学大纲，</p>
            <p>自动生成实验室申请登记表，</p>
            <p>文件格式为.pdf</p>
          </div>
        </Tooltip>
        <Divider type="vertical"/>
        <Tooltip placement="bottom-start">
          <Button :class="{ 'import-form-btn': this.interactiveData.canImportHistory }" :size="btnSize" style="margin-left: 5px;" @click="appliedListModal = true" :disabled="!this.interactiveData.canImportHistory">
            导入历史申请表
            <font-awesome-icon icon="table"/>
          </Button>
          <div slot="content" v-if="this.interactiveData.canImportHistory">
            <p>从普通课程历史申请表列表中，</p>
            <p>选择合适的申请表，点击'选择'，</p>
            <p>自动生成实验室申请登记表</p>
            <p>(仅导入实验教材与实验项目)</p>
          </div>
          <div slot="content" v-else>
            <p>请先完善 学院、教师、课程、班级</p>
            <p>信息，方可导入历史申请表。(仅导</p>
            <p>入 实验教材 与 实验项目，其他信息</p>
            <p>不作更改)</p>
          </div>
        </Tooltip>
      </div>
      <br>
      <apply-form
        ref="applyForm"
        v-bind.sync="interactiveData"
        :pdfData="pdfData"
        @hide-spin="hideSpin"
        v-on:update:submitLoading="interactiveData.submitLoading = $event"
        v-on:update:teacher_code="interactiveData.teacher_code = $event"
        v-on:update:course_code="interactiveData.course_code = $event"
        v-on:update:canImportHistory="interactiveData.canImportHistory = $event"></apply-form>
      <div id="actions" class="text-center position-relative" v-if="interactiveData.teacher_code && interactiveData.course_code">
        <Poptip
            confirm
            title="确定提交表单吗？"
            word-wrap
            width="180"
            @on-ok="submitButton"
            class="text-left"
            :options="popperOpts">
            <Button type="success" :loading="interactiveData.submitLoading" class="mr-20">
              <span v-if="!this.interactiveData.submitLoading">提交表单</span>
              <span v-else>提交中...</span>
            </Button>
        </Poptip>
        <Poptip
            confirm
            title="数据将不可恢复，确定重置表单吗？"
            word-wrap
            width="180"
            @on-ok="resetButton"
            class="text-left"
            :options="popperOpts">
          <Button style="margin-left: 8px" :disabled="this.interactiveData.submitLoading">重置表单</Button>
        </Poptip>
      </div>
    </Card>
    <Modal v-model="appliedListModal" width="90" footer-hide>
      <p slot="header" class="text-center" style="color: #ffa352;">请在下方的历史申请表中选择合适的申请表</p>
      <applied-list v-if="appliedListModal" :showSelectBtn="true" :hideCheckBox="true" :hideOperationBtn="true" :formType="['COURSE']" @selectedPastForm="getPastFormByCode"></applied-list>
    </Modal>
  </div>
</template>
<script>
import ApplyForm from '_c/apply-form'
import AppliedList from '_c/applied-list/applied-list'
import { on, off, generateGuid } from '@/libs/tools'
import { getFormDetailByCode } from '@/api/apply-form'

import { library } from '@fortawesome/fontawesome-svg-core'
import { faFilePdf, faTable } from '@fortawesome/free-solid-svg-icons'

library.add(faFilePdf)
library.add(faTable)

export default {
  components: {
    // 使用 key: value 的形式注册 value 组件，并命名为 key
    'apply-form': ApplyForm,
    'applied-list': AppliedList
  },
  data () {
    return {
      showUploadList: false,
      btnSize: 'default',
      appliedListModal: false,
      interactiveData: {
        submitLoading: false,
        teacher_code: null,
        course_code: null,
        canImportHistory: false
      },
      popperOpts: {
        modifiers: {
          preventOverflow: {
            // 边界元素: scrollParent, window, viewport or any DOM element. 默认iview默认window
            boundariesElement: 'scrollParent'
          }
        }
      },
      pdfData: {}
    }
  },
  created () {
    // 全局配置notice组件的属性
    this.$Notice.config({
      top: window.innerHeight / 3
    })
  },
  methods: {
    /* 事件处理函数不能设置为async */
    handleUpload (file) {
      this.$Spin.show({
        render: (h) => {
          return h('div', {'class': 'ivu-spin-large'}, [
            h('span', {
              'class': 'ivu-spin-dot',
              style: {
                display: 'inline-block'
              }
            }),
            h('div', '上传并解析PDF中，请稍等...')
          ])
        }
      })
      this.resolvePDF(file)
      return false
    },
    // 解析pdf内容
    resolvePDF (file) {
      // 将文件转为base64编码
      let reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = progressEvent => {
        // 将base64编码的文件，替换多余的空格和换行（为了兼容其他浏览器），再使用浏览器自带的atob()的方式解析
        let data = reader.result.replace(/[\r\n]/g, '')
        let raw = window.atob(data.substring(data.indexOf(',') + 1))
        let rawLength = raw.length
        let array = new Uint8Array(new ArrayBuffer(rawLength))
        for (let i = 0; i < rawLength; i++) {
          array[i] = raw.charCodeAt(i)
        }
        this.$getPDFContent(array).then(result => {
          this.getDataFromPDF(result)
        }).catch(error => {
          console.log(error)
          this.$Spin.hide()
          this.$Notice.error({
            title: '导入pdf失败',
            desc: '解析pdf文件出错！请导入正确格式的pdf文件！'
          })
        })
      }
      reader.onerror = error => {
        console.log(error)
        this.$Spin.hide()
      }
    },
    // 通过appCode获取历史申请表的详细信息
    async getPastFormByCode (code) {
      try {
        let res = await getFormDetailByCode(code)
        res = res.data
        if (res.code) {
          // 关闭选择历史申请表的modal
          this.appliedListModal = false
          let formData = res.data
          this.$refs['applyForm'].fillFormByData(formData)
        } else {
          this.$Message.error('抱歉，获取申请表信息失败，请刷新后重试')
        }
      } catch (error) {
        console.log(error)
        this.$Message.error('抱歉，获取申请表信息失败，请刷新后重试')
      }
    },
    submitButton () {
      this.$refs['applyForm'].handleSubmit('applyForm')
    },
    resetButton () {
      this.$refs['applyForm'].handleReset('applyForm', true)
    },
    // 从解析出的pdf数组中获取对应的课程信息
    getDataFromPDF (source) {
      /**
       * 获取：课程名称、授课对象、任课教师姓名/职称、使用教材
       */
      const actions = new Map([
        ['开课院系：', (i, index) => {
          if (source[i].items[index + 1].str !== '开课院系：') {
            data.institute = source[i].items[index + 1].str.trim()
          }
        }],
        ['课程名称：', (i, index) => {
          if (source[i].items[index + 1].str !== '课程名称：') {
            index++
            data.course_code = ''
            while (!(source[i].items[index].str === '课程类别（必修' || source[i].items[index].str === '课程类别（必修/选修）：')) {
              data.course_code += source[i].items[index].str.trim()
              index++
            }
          }
        }],
        ['授课对象：', (i, index) => {
          if (source[i].items[index + 1].str !== '授课对象：') {
            data.teach_object = source[i].items[index + 1].str.trim().replace(/[,，、]/g, ';').split(';')
          }
        }],
        ['职称：', (i, index) => {
          if (source[i].items[index + 1].str !== '职称：') {
            data.teacher_name = source[i].items[index + 1].str.trim()
          }
        }],
        ['使用教材：', (i, index) => {
          index++
          data.textbook = ''
          while (source[i].items[index].str !== '参考教材：') {
            data.textbook += source[i].items[index].str.trim()
            index++
          }
        }],
        ['default', (i, index) => {
          return undefined
        }]
      ])
      // 根据 ‘项目类型’ 关键字获取大致对应的项目类型
      const getStype = new Map([
        ['演示', '演示性'],
        ['验证', '验证性'],
        ['创新', '创新性'],
        ['练习', '练习性'],
        ['设计', '设计性'],
        ['综合', '综合性'],
        // ['综合设计', '综合设计性'],
        // ['设计研究', '设计研究性'],
        ['default', '其他']
      ])
      let data = {}
      data.expBaseInfoItems = []
      // 存储“实践教学进程表”的内容
      let expItems = []
      // 起始终止条件
      let expFlag = false
      /**
       * 遍历PDF文本内容
       */
      for (let i = 0; i < source.length; i++) {
        source[i].items.filter(function (elem, index, arr) {
          let action = actions.get(elem.str) || actions.get('default')
          // 获取课程名称、授课对象、任课教师姓名/职称、使用教材
          action.call(this, i, index)
          /*
           * 获取“实践教学进程表”内容
           */
          if (elem.str === '实践教学进程表') {
            expFlag = true
          }
          if (elem.str === '合计：') {
            expFlag = false
          }
          if (expFlag) {
            expItems.push(elem)
          }
        })
      }
      // 去掉“实践教学进程表”内容前面多余的重复大标题，只保留实验项目items
      // expItems.splice(0,
      //   expItems[21].str === '本课程与学生核心能力培养之间的关联（可多选）：' ? 22
      //     : expItems[19].str === '本课程与学生核心能力培养之间的关联（可多选）：' || expItems[19].str === '式' ? 20 : 18)
      // 获取周次的transform[4]的最大值
      let weekTransform4Max = expItems.slice(2, 4).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x > y ? x : y
      })
      // 获取实验项目名称的transform[4]的最小值
      let expNameTransform4Min = expItems.slice(4, 6).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x < y ? x : y
      })
      // 获取实验项目名称的transform[4]的最大值
      let expNameTransform4Max = expItems.slice(4, 6).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x > y ? x : y
      })
      // 获取学时的transform[4]的最小值
      let leanrTimeTransform4Min = expItems.slice(6, 8).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x < y ? x : y
      })
      // 获取学时的transform[4]的最大值
      let leanrTimeTransform4Max = expItems.slice(6, 8).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x > y ? x : y
      })
      // 获取重点与难点的transform[4]的最小值
      let importantTransform4Min = expItems.slice(8, 10).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x < y ? x : y
      })
      // 获取学时的transform[4]的最大值
      let importantTransform4Max = expItems.slice(8, 10).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x > y ? x : y
      })
      // 获取项目类型的transform[4]的最小值
      let expTypeTransform4Min = expItems.slice(10, 12).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x < y ? x : y
      })
      // 获取项目类型的transform[4]的最大值
      let expTypeTransform4Max = expItems.slice(10, 12).map(item => {
        return item.transform[4]
      }).reduce((x, y) => {
        return x > y ? x : y
      })
      // 去掉“实践教学进程表”内容前面多余的重复大标题，只保留实验项目items
      expItems.splice(0, 14)
      // 存储处理后的实验项目信息
      let expArray = [['']]
      // 每个实验项目的下标
      let expArrIndex = 0
      // 每个实验项目里面每个小元素的下标
      let expItemIndex = 0
      for (let i = 0; i < expItems.length; i++) {
        if (!(expItems[i].transform[4] > leanrTimeTransform4Max && expItems[i].transform[4] < expTypeTransform4Min)) {
          if (expItemIndex === 0 && expItems[i].transform[4] <= expNameTransform4Min - 5) {
            // 获取周次
            expArray[expArrIndex][expItemIndex] += expItems[i].str
          } else if (expItemIndex === 1 && expItems[i].transform[4] >= weekTransform4Max && expItems[i].transform[4] <= leanrTimeTransform4Min - 5) {
            // 获取实验项目名称
            expArray[expArrIndex][expItemIndex] += expItems[i].str
          } else if (expItemIndex === 2 && expItems[i].transform[4] >= expNameTransform4Max && expItems[i].transform[4] <= importantTransform4Min) {
            // 获取学时
            expArray[expArrIndex][expItemIndex] += expItems[i].str
          } else if (expItemIndex === 3 && expItems[i].transform[4] >= importantTransform4Max && expItems[i].transform[4] <= expTypeTransform4Min) {
            // 获取实验类型
            expArray[expArrIndex][expItemIndex] += expItems[i].str
          } else if (expItemIndex === 4 && expItems[i].transform[4] >= expTypeTransform4Max) {
            // 获取教学方式
            expArray[expArrIndex][expItemIndex] += expItems[i].str
          } else {
            /**
             * 1.当“教学方式”有两行时，执行完上面的拼接之后，下一个的item是新项目数据的item，但是expItemIndex依然维持在5，
             *   所以需要 判断假设expItemIndex为4时，expItemIndex置为0，且新增一个expArr，然后下面才会赋值给新的expArr
             * 2.如果不为5的话，即为当前项目的数据，直接expItemIndex++即可
             */
            if (expItemIndex === 4) {
              expItemIndex = 0
              expArrIndex++
              expArray.push([
                ''
              ])
            } else {
              expItemIndex++
            }
            expArray[expArrIndex][expItemIndex] = expItems[i].str
          }
        }
      }
      for (let i = 0; i < expArray.length; i++) {
        data.expBaseInfoItems.push({
          guid: generateGuid(),
          sid: i + 1,
          type: getStype.get(expArray[i][3].slice(0, 2)) || getStype.get('default'),
          title: expArray[i][1],
          learntime: parseInt(expArray[i][2]),
          laboratoryList: [],
          classroom: [],
          resources: null,
          system: null,
          software: null,
          expTimeItems: []
        })
        // 把周次按 ', | ，| - | ~ '分割成数组
        let weekArray = []
        if (expArray[i][0].indexOf('-') > -1 || expArray[i][0].indexOf('~') > -1) {
          let weekRange = expArray[i][0].replace(/[-~]/g, ',').split(',')
          if (weekRange && weekRange.length === 2) {
            let min = Number(weekRange[0])
            let max = Number(weekRange[1])
            for (let i = min; i <= max; i++) {
              weekArray.push(i.toString())
            }
          } else {
            weekArray = expArray[i][0].replace(/[-~]/g, ',').split(',')
          }
        } else {
          weekArray = expArray[i][0].replace(/[,，、]/g, ',').split(',')
        }
        weekArray.forEach(item => {
          data.expBaseInfoItems[data.expBaseInfoItems.length - 1].expTimeItems.push({
            guid: generateGuid(),
            sweek: parseInt(item),
            institute: this.$refs['applyForm'].applyForm.institute,
            sdate: null,
            section: [],
            classroom: null,
            laboratoryList: [],
            labLoading: false
          })
        })
      }
      this.pdfData = JSON.parse(JSON.stringify(data))
    },
    hideSpin () {
      this.$Spin.hide()
    },
    resizeSubComponents () {
      this.$children[0].$el.children[0].style.minHeight = this.$parent.$el.clientHeight - 36 + 'px'
    }
  },
  mounted () {
    this.$nextTick(() => {
      this.resizeSubComponents()
      on(window, 'resize', this.resizeSubComponents)
    })
  },
  beforeDestroy () {
    off(window, 'resize', this.resizeSubComponents)
  }
}
</script>

<style lang="less">
  @import './apply-form.less';
</style>
